import { ifUidInTeam, segmentedCoef, setUserStatus } from '@src/apps/tools'
import {
  team,
  user_attribute,
  user_equipment,
  ioredis,
  race_base,
  equipment_list,
  race_extra,
  battle,
  user
} from '@src/db'

/**
 * 战斗初始化函数
 * 输入用户uid，将user_attribute表中的数据保存到内存数据库
 * @param uid 用户uid
 */
export async function battleInitialization(
  user_members: any[], //取自loadPlayerAttributes函数的返回值
  enemy_members: any[], //取自loadEnemyAttributes函数的返回值
  type: string // 战斗类型
): Promise<void> {
  // 生成唯一 battle_id
  const allBattleIds = await battle.findAllValues({ attributes: ['battle_id'] })
  const usedIds = allBattleIds
    .map((b: any) => Number(b.battle_id))
    .filter(id => !isNaN(id))
  let battle_id = 1
  while (usedIds.includes(battle_id)) {
    battle_id++
  }

  // 写入用户成员到 battle 表，阵营为1
  let userIndex = 1
  const userCamp = 1
  for (const member of user_members) {
    await battle.create({
      battle_id,
      battle_type: type,
      battle_camp: userCamp,
      battle_index: member.position, // 添加索引字段
      ...member
    })
    // 将用户属性写入内存数据库
    await ioredis.hmset(
      `fantasy:battle:${battle_id}:${userCamp}:${member.position}:info`,
      member
    )
    // 用户状态改为战斗
    await setUserStatus(member.uid, 6)
    userIndex++
  }

  // 写入敌方成员到 battle 表，阵营为2
  let enemyIndex = 1
  const enemyCamp = 2
  for (const member of enemy_members) {
    await battle.create({
      battle_id,
      battle_type: type,
      battle_camp: enemyCamp,
      battle_index: member.position, // 添加索引字段
      ...member
    })
    // 将敌方属性写入内存数据库
    await ioredis.hmset(
      `fantasy:battle:${battle_id}:${enemyCamp}:${member.position}:info`,
      member
    )
    // 敌方状态改为战斗
    if (member.uid >= 10000000) {
      await setUserStatus(member.uid, 6)
    }
    enemyIndex++
  }

  // 内存数据库写入回合数
  await ioredis.set(`fantasy:battle:${battle_id}:round`, 0)
}

/**
 * 加载玩家（或队伍）属性
 * @param uid 用户uid
 * @returns Promise<user_attribute[]> 队伍成员或单人属性数组
 */
export async function loadPlayerAttributes(uid: number): Promise<any[]> {
  // 需要的字段
  const fields = [
    'uid',
    'name',
    'race',
    'affixes',
    'equips',
    'level',
    'position',
    'constitution',
    'spirit',
    'strength',
    'intelligence',
    'agility',
    'perception',
    'charm',
    'luck',
    'hp_max',
    'mp_max',
    'hp',
    'mp',
    'atk',
    'matk',
    'def',
    'mdef',
    'hit',
    'dodge',
    'crit',
    'crit_dmg',
    'crit_avoid',
    'crit_resist',
    'speed',
    'tenacity',
    'hp_recover',
    'mp_recover',
    'stab_mastery',
    'slash_mastery',
    'strike_mastery',
    'stab_resist',
    'slash_resist',
    'strike_resist',
    'metal_mastery',
    'wood_mastery',
    'water_mastery',
    'fire_mastery',
    'earth_mastery',
    'ice_mastery',
    'thunder_mastery',
    'wind_mastery',
    'light_mastery',
    'dark_mastery',
    'metal_resist',
    'wood_resist',
    'water_resist',
    'fire_resist',
    'earth_resist',
    'ice_resist',
    'thunder_resist',
    'wind_resist',
    'light_resist',
    'dark_resist'
  ]

  // 判断是否在队伍中
  const inTeam = await ifUidInTeam(uid)
  if (inTeam) {
    // 查找所在队伍
    const teams = await team.findAllValues({})
    for (const t of teams) {
      if (Array.isArray(t.members) && t.members.includes(String(uid))) {
        // 提取队伍所有成员uid
        const uids = t.members.map((id: any) => Number(id))
        // 读取站位信息（假设team表有player_1~player_6字段，分别对应members[0]~members[5]）
        const positions: Record<number, number> = {}
        for (let i = 0; i < t.members.length; i++) {
          const memberUid = Number(t.members[i])
          // 站位列名如 player_1, player_2, ...
          const posCol = `player_${i + 1}`
          positions[memberUid] = t[posCol] ?? i + 1
        }

        // 读取所有成员属性
        const attrs = await user_attribute.findAllValues({
          where: { uid: uids }
        })
        // 查询所有成员的name
        const userInfos = await user.findAllValues({ where: { uid: uids } })
        const uidNameMap: Record<number, string> = {}
        userInfos.forEach(u => {
          uidNameMap[u.uid] = u.name
        })

        // 组装初步结果，优先用队伍分配的站位，否则顺序分配
        let result = attrs.map((item: any, idx: number) => {
          const obj: any = {}
          for (const key of fields) obj[key] = item[key]
          obj.position = positions[item.uid] ?? item.position ?? idx + 1
          obj.name = uidNameMap[item.uid] || item.name || `成员${item.uid}`
          return obj
        })

        // 统计已分配的position
        const usedPositions = new Set<number>()
        result.forEach(obj => {
          if (
            obj.position >= 1 &&
            obj.position <= 6 &&
            !usedPositions.has(obj.position)
          ) {
            usedPositions.add(obj.position)
          }
        })

        // 处理重复或非法的position（只保留第一个，后面重复的重新分配）
        for (let i = 0; i < result.length; i++) {
          const obj = result[i]
          if (
            obj.position < 1 ||
            obj.position > 6 ||
            result.findIndex(o => o.position === obj.position) !== i
          ) {
            // 分配未用的位置
            for (let p = 1; p <= 6; p++) {
              if (!usedPositions.has(p)) {
                obj.position = p
                usedPositions.add(p)
                break
              }
            }
          }
        }
        return result
      }
    }
    return []
  } else {
    // 单人
    const attr = await user_attribute.findOneValue({ where: { uid } })
    if (!attr) return []
    const userInfo = await user.findOneValue({ where: { uid } })
    const obj: any = {}
    for (const key of fields) obj[key] = attr[key]
    obj.position = 1 // 单人默认位置为1
    obj.name = userInfo?.name || `成员${uid}`

    // user_equipment数据表读取装备加入数组
    const equips = await user_equipment.findAllValues({ where: { uid } })
    // 里面有weapon, sub_weapon, shoulder, upper, waist, lower, foot, bracelet, ring, necklace字段
    const equipped: Record<string, string> = {}
    equips.forEach(equip => {
      if (equip.weapon) equipped.weapon = equip.weapon
      if (equip.sub_weapon) equipped.sub_weapon = equip.sub_weapon
      if (equip.shoulder) equipped.shoulder = equip.shoulder
      if (equip.upper) equipped.upper = equip.upper
      if (equip.waist) equipped.waist = equip.waist
      if (equip.lower) equipped.lower = equip.lower
      if (equip.foot) equipped.foot = equip.foot
      if (equip.bracelet) equipped.bracelet = equip.bracelet
      if (equip.ring) equipped.ring = equip.ring
      if (equip.necklace) equipped.necklace = equip.necklace
    })
    obj.equips = Object.values(equipped).filter(name => name) // 过滤掉空值

    return [obj]
  }
}

/**
 * 生成敌人属性
 * @param race_name 种族名
 * @param level 等级
 * @param affixes 词条数组
 * @param equipped 已装备字典 { 部位: 装备名 }
 * @returns 敌人属性对象
 */
export async function makeEnemy(
  name: string,
  race_name: string,
  level: number,
  affixes: string[],
  equipped: Record<string, string>
) {
  // 1. 获取种族基础属性
  const race = await race_base.findOneValue({ where: { race_name } })
  if (!race) throw new Error('未找到该种族')

  // 2. 基础属性成长（基础属性 + 成长 * level）
  let constitution =
    race.constitution_base + (race.constitution_growth || 0) * level
  let spirit = race.spirit_base + (race.spirit_growth || 0) * level
  let strength = race.strength_base + (race.strength_growth || 0) * level
  let intelligence =
    race.intelligence_base + (race.intelligence_growth || 0) * level
  let agility = race.agility_base + (race.agility_growth || 0) * level
  let perception = race.perception_base + (race.perception_growth || 0) * level
  let charm = race.charm_base + (race.charm_growth || 0) * level
  let luck = race.luck_base + (race.luck_growth || 0) * level
  let stab_mastery = race.stab_mastery || 0
  let slash_mastery = race.slash_mastery || 0
  let strike_mastery = race.strike_mastery || 0
  let stab_resist = race.stab_resist || 0
  let slash_resist = race.slash_resist || 0
  let strike_resist = race.strike_resist || 0
  let metal_mastery = race.metal_mastery || 0
  let wood_mastery = race.wood_mastery || 0
  let water_mastery = race.water_mastery || 0
  let fire_mastery = race.fire_mastery || 0
  let earth_mastery = race.earth_mastery || 0
  let ice_mastery = race.ice_mastery || 0
  let thunder_mastery = race.thunder_mastery || 0
  let wind_mastery = race.wind_mastery || 0
  let light_mastery = race.light_mastery || 0
  let dark_mastery = race.dark_mastery || 0
  let metal_resist = race.metal_resist || 0
  let wood_resist = race.wood_resist || 0
  let water_resist = race.water_resist || 0
  let fire_resist = race.fire_resist || 0
  let earth_resist = race.earth_resist || 0
  let ice_resist = race.ice_resist || 0
  let thunder_resist = race.thunder_resist || 0
  let wind_resist = race.wind_resist || 0
  let light_resist = race.light_resist || 0
  let dark_resist = race.dark_resist || 0
  let base_skill = race.base_skill || []

  // 3. 词条额外属性加成（包括成长）
  for (const affix of affixes) {
    const extra = await race_extra.findOneValue({
      where: { race_name, affixes: affix }
    })
    if (extra) {
      constitution +=
        (extra.constitution_base || 0) +
        (extra.constitution_growth || 0) * level
      spirit += (extra.spirit_base || 0) + (extra.spirit_growth || 0) * level
      strength +=
        (extra.strength_base || 0) + (extra.strength_growth || 0) * level
      intelligence +=
        (extra.intelligence_base || 0) +
        (extra.intelligence_growth || 0) * level
      agility += (extra.agility_base || 0) + (extra.agility_growth || 0) * level
      perception +=
        (extra.perception_base || 0) + (extra.perception_growth || 0) * level
      charm += (extra.charm_base || 0) + (extra.charm_growth || 0) * level
      luck += (extra.luck_base || 0) + (extra.luck_growth || 0) * level
    }
  }

  // 4. 计算最终属性
  const constitution_final = constitution
  const spirit_final = spirit
  const strength_final = strength
  const intelligence_final = intelligence
  const agility_final = agility
  const perception_final = perception
  const charm_final = charm
  const luck_final = luck

  // 5. 读取装备加成
  let equipAdd = {
    constitution: 0,
    spirit: 0,
    strength: 0,
    intelligence: 0,
    agility: 0,
    perception: 0,
    charm: 0,
    luck: 0,
    hp_max: 0,
    mp_max: 0,
    atk: 0,
    matk: 0,
    def: 0,
    mdef: 0,
    hit: 0,
    dodge: 0,
    crit: 0,
    crit_dmg: 0,
    crit_avoid: 0,
    crit_resist: 0,
    speed: 0,
    tenacity: 0,
    hp_recover: 0,
    mp_recover: 0
  }
  for (const equipName of Object.values(equipped)) {
    if (!equipName) continue
    const eq = await equipment_list.findOneValue({ where: { name: equipName } })
    if (eq) {
      equipAdd.constitution += eq.constitution || 0
      equipAdd.spirit += eq.spirit || 0
      equipAdd.strength += eq.strength || 0
      equipAdd.intelligence += eq.intelligence || 0
      equipAdd.agility += eq.agility || 0
      equipAdd.perception += eq.perception || 0
      equipAdd.charm += eq.charm || 0
      equipAdd.luck += eq.luck || 0
      equipAdd.hp_max += eq.hp_max || 0
      equipAdd.mp_max += eq.mp_max || 0
      equipAdd.atk += eq.atk || 0
      equipAdd.matk += eq.matk || 0
      equipAdd.def += eq.def || 0
      equipAdd.mdef += eq.mdef || 0
      equipAdd.hit += eq.hit || 0
      equipAdd.dodge += eq.dodge || 0
      equipAdd.crit += eq.crit || 0
      equipAdd.crit_dmg += eq.crit_dmg || 0
      equipAdd.crit_avoid += eq.crit_avoid || 0
      equipAdd.crit_resist += eq.crit_resist || 0
      equipAdd.speed += eq.speed || 0
      equipAdd.tenacity += eq.tenacity || 0
      equipAdd.hp_recover += eq.hp_recover || 0
      equipAdd.mp_recover += eq.mp_recover || 0
    }
  }

  // 装备名称数组
  const equips = Object.values(equipped).filter(name => name) // 过滤掉空值

  // 6. 属性系数计算
  const constitution_segment = segmentedCoef(constitution_final)
  const spirit_segment = segmentedCoef(spirit_final)
  const strength_segment = segmentedCoef(strength_final)
  const intelligence_segment = segmentedCoef(intelligence_final)
  const agility_segment = segmentedCoef(agility_final)
  const perception_segment = segmentedCoef(perception_final)
  const charm_segment = segmentedCoef(charm_final)
  const luck_segment = segmentedCoef(luck_final)

  // 7. 衍生属性计算
  const hp_max =
    (equipAdd.hp_max + constitution_final * 5) * (1 + constitution_segment)
  const mp_max = (equipAdd.mp_max + spirit_final * 5) * (1 + spirit_segment)
  const atk = (equipAdd.atk + strength_final * 1) * (1 + strength_segment)
  const matk =
    (equipAdd.matk + intelligence_final * 1) * (1 + intelligence_segment)
  const def =
    (equipAdd.def + constitution_final * 1) *
    (1 + constitution_segment * 0.75 + strength_segment * 0.25)
  const mdef =
    (equipAdd.mdef + spirit_final * 1) *
    (1 + spirit_segment * 0.75 + intelligence_segment * 0.25)
  const hit =
    (equipAdd.hit +
      agility_final * 2 +
      strength_final * 1 +
      intelligence_final * 1 +
      luck_final * 10) *
    (1 + agility_segment + luck_segment)
  const dodge =
    (equipAdd.dodge + agility_final * 2 + luck_final * 10) *
    (1 + agility_segment + luck_segment)
  const crit =
    (equipAdd.crit + strength_final * 4 + luck_final * 10) *
    (1 + agility_segment * 0.25 + perception_segment * 0.75 + luck_segment)
  const crit_dmg =
    (equipAdd.crit_dmg + intelligence_final * 4 + luck_final * 10) *
    (1 + agility_segment * 0.25 + perception_segment * 0.75 + luck_segment)
  const crit_avoid =
    (equipAdd.crit_avoid + constitution_final * 1 + spirit_final * 1) *
    (1 + perception_segment * 0.5 + spirit_segment * 0.5)
  const crit_resist =
    (equipAdd.crit_resist + constitution_final * 1 + spirit_final * 1) *
    (1 + constitution_segment * 0.5 + perception_segment * 0.5)
  const speed = (equipAdd.speed + agility_final * 4) * (1 + agility_segment)
  const tenacity =
    (equipAdd.tenacity + constitution_final * 1 + spirit_final * 1) *
    (1 + constitution_segment * 0.5 + spirit_segment * 0.5)
  const hp_recover =
    (equipAdd.hp_recover + constitution_final * 1) * (1 + constitution_segment)
  const mp_recover =
    (equipAdd.mp_recover + spirit_final * 1) * (1 + spirit_segment)

  // 8. 返回属性对象，属性数值取整
  return {
    name,
    race: race_name,
    affixes,
    equips,
    level: level,
    constitution: constitution_final,
    spirit: spirit_final,
    strength: strength_final,
    intelligence: intelligence_final,
    agility: agility_final,
    perception: perception_final,
    charm: charm_final,
    luck: luck_final,
    hp_max: Math.floor(hp_max),
    mp_max: Math.floor(mp_max),
    hp: Math.floor(hp_max),
    mp: Math.floor(mp_max),
    atk: Math.floor(atk),
    matk: Math.floor(matk),
    def: Math.floor(def),
    mdef: Math.floor(mdef),
    hit: Math.floor(hit),
    dodge: Math.floor(dodge),
    crit: Math.floor(crit),
    crit_dmg: Math.floor(crit_dmg),
    crit_avoid: Math.floor(crit_avoid),
    crit_resist: Math.floor(crit_resist),
    speed: Math.floor(speed),
    tenacity: Math.floor(tenacity),
    hp_recover: Math.floor(hp_recover),
    mp_recover: Math.floor(mp_recover),
    stab_mastery,
    slash_mastery,
    strike_mastery,
    stab_resist,
    slash_resist,
    strike_resist,
    metal_mastery,
    wood_mastery,
    water_mastery,
    fire_mastery,
    earth_mastery,
    ice_mastery,
    thunder_mastery,
    wind_mastery,
    light_mastery,
    dark_mastery,
    metal_resist,
    wood_resist,
    water_resist,
    fire_resist,
    earth_resist,
    ice_resist,
    thunder_resist,
    wind_resist,
    light_resist,
    dark_resist,
    skill_land: base_skill
  }
}

/**
 * 加载敌人属性
 * @param enemyList 敌人属性对象数组（每项包含 race_name, level, affixes, equipped 等 makeEnemy 输入参数）
 * @returns 敌人属性数组（每项为 makeEnemy 的输出结果）
 * @throws 输入不是数组时抛出错误
 */
export async function loadEnemyAttributes(
  enemyList: {
    name: string
    race_name: string
    level: number
    affixes: string[]
    equipped: Record<string, string>
    where?: string
  }[]
): Promise<any[]> {
  if (!Array.isArray(enemyList)) {
    throw new Error('enemyList 必须为数组')
  }

  // 可用前排和后排位置
  const frontPositions = [1, 2, 3]
  const backPositions = [4, 5, 6]
  const usedPositions: number[] = []

  // 统计where指定的数字，避免重复
  const whereMap: Record<number, number> = {}

  // 先处理所有where为数字的情况，分配指定位置
  const assignedPositions: (number | undefined)[] = enemyList.map(e => {
    const posNum = Number(e.where)
    if (
      !isNaN(posNum) &&
      posNum >= 1 &&
      posNum <= 6 &&
      !usedPositions.includes(posNum)
    ) {
      usedPositions.push(posNum)
      whereMap[posNum] = (whereMap[posNum] || 0) + 1
      return posNum
    }
    return undefined
  })

  // 处理重复where，优先同排未用位置
  for (let i = 0; i < enemyList.length; i++) {
    if (assignedPositions[i] !== undefined) continue
    const e = enemyList[i]
    const posNum = Number(e.where)
    if (!isNaN(posNum) && posNum >= 1 && posNum <= 6) {
      // 有重复，分配同排未用位置
      const pool = posNum <= 3 ? frontPositions : backPositions
      const available = pool.filter(p => !usedPositions.includes(p))
      if (available.length > 0) {
        assignedPositions[i] = available[0]
        usedPositions.push(available[0])
      }
    }
  }

  // 剩余未分配的，依次分配剩余空位
  const allPositions = [...frontPositions, ...backPositions]
  for (let i = 0; i < enemyList.length; i++) {
    if (assignedPositions[i] === undefined) {
      const available = allPositions.find(p => !usedPositions.includes(p))
      assignedPositions[i] = available
      if (available !== undefined) usedPositions.push(available)
    }
  }

  // 并发调用 makeEnemy，返回所有结果，并为每一项加上uid和position
  const result = await Promise.all(
    enemyList.map(e =>
      makeEnemy(e.name, e.race_name, e.level, e.affixes, e.equipped)
    )
  )
  // 为每个敌人加上uid和position字段
  const enemy_result = result.map((item, idx) => ({
    ...item,
    uid: idx + 1,
    camp: 2, // 敌人阵营为2
    index: idx + 1,
    position: assignedPositions[idx] ?? idx + 1
  }))
  return enemy_result
}
